package com.gitee.dbswitch.data.util;

import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.util.Map;

/**
 * @author natural
 */
@Slf4j
public final class OKHttpUtils {
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final MediaType XML = MediaType.parse("application/xml; charset=utf-8");

    private static final OkHttpClient okHttpClient;

    static {
        okHttpClient = new OkHttpClient();
    }

    public static Object doRequest(String url, Map<String, String> params, Map<String, String> headers, String body, String requestType) {
        Request.Builder requestBuilder = new Request.Builder();
        if (headers != null && !headers.isEmpty()) {
            for (String header : headers.keySet()) {
                requestBuilder.addHeader(header, headers.get(header));
            }
        }

        switch (requestType) {
            case "GET":
            case "GET_BYTE":
                StringBuilder sb = new StringBuilder(url);
                if (params != null && !params.keySet().isEmpty()) {
                    boolean firstFlag = true;
                    for (String key : params.keySet()) {
                        if (firstFlag) {
                            sb.append("?").append(key).append("=").append(params.get(key));
                            firstFlag = false;
                        } else {
                            sb.append("&").append(key).append("=").append(params.get(key));
                        }
                    }
                }
                requestBuilder.url(sb.toString()).get();
                Request getRequest = requestBuilder.build();
                if ("GET".equals(requestType)) {
                    return executeBody(getRequest);
                } else {
                    return executeByte(getRequest);
                }
            case "POST_FORM":
                FormBody.Builder formBuilder = new FormBody.Builder();
                if (params != null && !params.keySet().isEmpty()) {
                    for (String key : params.keySet()) {
                        formBuilder.add(key, params.get(key));
                    }
                }
                requestBuilder.url(url).post(formBuilder.build());
                return execute(requestBuilder.build());
            case "POST_JSON":
                RequestBody jsonRequestBody = RequestBody.create(JSON, body);
                requestBuilder.url(url).post(jsonRequestBody);
                return execute(requestBuilder.build());
            case "POST_XML":
                RequestBody xmlRequestBody = RequestBody.create(XML, body);
                requestBuilder.url(url).post(xmlRequestBody);
                return execute(requestBuilder.build());
            default:
                throw new IllegalArgumentException("Unknown request type: " + requestType);
        }
    }

    private static String execute(Request request) {
        try (Response response = okHttpClient.newCall(request).execute()) {
            if (response.isSuccessful() && response.body() != null) {
                return response.body().string();
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
        }
        return "";
    }

    private static String executeBody(Request request) {
        try (Response response = okHttpClient.newCall(request).execute()) {
            if (response.body() != null) {
                return response.body().string();
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
        }
        return "";
    }

    private static byte[] executeByte(Request request) {
        try (Response response = okHttpClient.newCall(request).execute()) {
            if (response.isSuccessful() && response.body() != null) {
                return response.body().bytes();
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
        }
        return null;
    }
}